---
title: "Semantic Recall | Memory"
description: "Learn how to use semantic recall in Mastra to retrieve relevant messages from past conversations using vector search and embeddings."
---

# Semantic Recall

If you ask your friend what they did last weekend, they will search in their memory for events associated with "last weekend" and then tell you what they did. That's sort of like how semantic recall works in Mastra.

> **📹 Watch**: What semantic recall is, how it works, and how to configure it in Mastra → [YouTube (5 minutes)](https://youtu.be/UVZtK8cK8xQ)

## How Semantic Recall Works

Semantic recall is RAG-based search that helps agents maintain context across longer interactions when messages are no longer within [recent conversation history](./conversation-history).

It uses vector embeddings of messages for similarity search, integrates with various vector stores, and has configurable context windows around retrieved messages.

<br />
<img
  src="/img/semantic-recall.png"
  alt="Diagram showing Mastra Memory semantic recall"
  width={800}
/>

When it's enabled, new messages are used to query a vector DB for semantically similar messages.

After getting a response from the LLM, all new messages (user, assistant, and tool calls/results) are inserted into the vector DB to be recalled in later interactions.

## Quick Start

Semantic recall is enabled by default, so if you give your agent memory it will be included:

```typescript {8}
import { Agent } from "@mastra/core/agent";
import { Memory } from "@mastra/memory";

const agent = new Agent({
  id: "support-agent",
  name: "SupportAgent",
  instructions: "You are a helpful support agent.",
  model: "openai/gpt-5.1",
  memory: new Memory(),
});
```

## Recall configuration

The three main parameters that control semantic recall behavior are:

1. **topK**: How many semantically similar messages to retrieve
2. **messageRange**: How much surrounding context to include with each match
3. **scope**: Whether to search within the current thread or across all threads owned by a resource (the default is resource scope).

```typescript {5-7}
const agent = new Agent({
  memory: new Memory({
    options: {
      semanticRecall: {
        topK: 3, // Retrieve 3 most similar messages
        messageRange: 2, // Include 2 messages before and after each match
        scope: "resource", // Search across all threads for this user (default setting if omitted)
      },
    },
  }),
});
```

### Storage configuration

Semantic recall relies on a [storage and vector db](/reference/v1/memory/memory-class) to store messages and their embeddings.

```ts {8-17}
import { Memory } from "@mastra/memory";
import { Agent } from "@mastra/core/agent";
import { LibSQLStore, LibSQLVector } from "@mastra/libsql";

const agent = new Agent({
  memory: new Memory({
    // this is the default storage db if omitted
    storage: new LibSQLStore({
      id: 'agent-storage',
      url: "file:./local.db",
    }),
    // this is the default vector db if omitted
    vector: new LibSQLVector({
      id: 'agent-vector',
      connectionUrl: "file:./local.db",
    }),
  }),
});
```

**Storage/vector code Examples**:

- [LibSQL](/docs/v1/memory/storage/memory-with-libsql)
- [MongoDB](/docs/v1/memory/storage/memory-with-mongodb)
- [Postgres](/docs/v1/memory/storage/memory-with-pg)
- [Upstash](/docs/v1/memory/storage/memory-with-upstash)

### Embedder configuration

Semantic recall relies on an [embedding model](/reference/v1/memory/memory-class) to convert messages into embeddings. Mastra supports embedding models through the model router using `provider/model` strings, or you can use any [embedding model](https://sdk.vercel.ai/docs/ai-sdk-core/embeddings) compatible with the AI SDK.

#### Using the Model Router (Recommended)

The simplest way is to use a `provider/model` string with autocomplete support:

```ts {7}
import { Memory } from "@mastra/memory";
import { Agent } from "@mastra/core/agent";
import { ModelRouterEmbeddingModel } from "@mastra/core/llm";

const agent = new Agent({
  memory: new Memory({
    // ... other memory options
    embedder: new ModelRouterEmbeddingModel("openai/text-embedding-3-small"),
  }),
});
```

Supported embedding models:

- **OpenAI**: `text-embedding-3-small`, `text-embedding-3-large`, `text-embedding-ada-002`
- **Google**: `gemini-embedding-001`, `text-embedding-004`

The model router automatically handles API key detection from environment variables (`OPENAI_API_KEY`, `GOOGLE_GENERATIVE_AI_API_KEY`).

#### Using AI SDK Packages

You can also use AI SDK embedding models directly:

```ts {2,7}
import { Memory } from "@mastra/memory";
import { Agent } from "@mastra/core/agent";
import { ModelRouterEmbeddingModel } from "@mastra/core/llm";

const agent = new Agent({
  memory: new Memory({
    // ... other memory options
    embedder: new ModelRouterEmbeddingModel("openai/text-embedding-3-small"),
  }),
});
```

#### Using FastEmbed (Local)

To use FastEmbed (a local embedding model), install `@mastra/fastembed`:

```bash npm2yarn copy
npm install @mastra/fastembed@beta
```

Then configure it in your memory:

```ts {3,8}
import { Memory } from "@mastra/memory";
import { Agent } from "@mastra/core/agent";
import { fastembed } from "@mastra/fastembed";

const agent = new Agent({
  memory: new Memory({
    // ... other memory options
    embedder: fastembed,
  }),
});
```

### PostgreSQL Index Optimization

When using PostgreSQL as your vector store, you can optimize semantic recall performance by configuring the vector index. This is particularly important for large-scale deployments with thousands of messages.

PostgreSQL supports both IVFFlat and HNSW indexes. By default, Mastra creates an IVFFlat index, but HNSW indexes typically provide better performance, especially with OpenAI embeddings which use inner product distance.

```typescript {9-18}
import { Memory } from "@mastra/memory";
import { PgStore, PgVector } from "@mastra/pg";

const agent = new Agent({
  memory: new Memory({
    storage: new PgStore({
      id: 'agent-storage',
      connectionString: process.env.DATABASE_URL,
    }),
    vector: new PgVector({
      id: 'agent-vector',
      connectionString: process.env.DATABASE_URL,
    }),
    options: {
      semanticRecall: {
        topK: 5,
        messageRange: 2,
        indexConfig: {
          type: "hnsw", // Use HNSW for better performance
          metric: "dotproduct", // Best for OpenAI embeddings
          m: 16, // Number of bi-directional links (default: 16)
          efConstruction: 64, // Size of candidate list during construction (default: 64)
        },
      },
    },
  }),
});
```

For detailed information about index configuration options and performance tuning, see the [PgVector configuration guide](/reference/v1/vectors/pg#index-configuration-guide).

### Disabling

There is a performance impact to using semantic recall. New messages are converted into embeddings and used to query a vector database before new messages are sent to the LLM.

Semantic recall is enabled by default but can be disabled when not needed:

```typescript {4}
const agent = new Agent({
  memory: new Memory({
    options: {
      semanticRecall: false,
    },
  }),
});
```

You might want to disable semantic recall in scenarios like:

- When conversation history provide sufficient context for the current conversation.
- In performance-sensitive applications, like realtime two-way audio, where the added latency of creating embeddings and running vector queries is noticeable.

## Viewing Recalled Messages

When tracing is enabled, any messages retrieved via semantic recall will appear in the agent’s trace output, alongside recent conversation history (if configured).

For more info on viewing message traces, see [Viewing Retrieved Messages](./overview#viewing-retrieved-messages).
